package com.haltakov.letterjumble.ai;

import java.util.ArrayList;

import com.haltakov.letterjumble.game.api.Dictionary;

public class TreeDictionary implements Dictionary {

	private class Node {
		char value;
		boolean isWord;
		ArrayList<Node> children;
		Node parent;
		
		public Node(char c, Node parent) {
			value = c;
			isWord = false;
			children = new ArrayList<Node>();
			this.parent = parent;
		}
		
		@Override
		public String toString() {
			return value + " " + children.toString();
		}
	}
	
	private int letterCount;
	private Node root;
	private int words = 0, letters = 0, nodes = 0; 
	
	public TreeDictionary(int letterCount) {
		this.letterCount = letterCount;
		root = new Node('-', null);
		root.children = new ArrayList<Node>(letterCount);
	}
	
	public int getWords() {
		return words;
	}

	public void setWords(int words) {
		this.words = words;
	}

	public int getLetters() {
		return letters;
	}

	public void setLetters(int letters) {
		this.letters = letters;
	}

	public int getNodes() {
		return nodes;
	}

	public void setNodes(int nodes) {
		this.nodes = nodes;
	}

	private Node findChar(char c, ArrayList<Node> list) {
		for (Node n: list) {
			if (n.value == c)
				return n;
		}
		return null;
	}
	
	private void addWordFromNode(String word, Node node) {
		Node n = findChar(word.charAt(0), node.children);
		
		if (n == null) {
			n = new Node(word.charAt(0), node);
			node.children.add(n);
			++nodes;
		}
		
		if (word.length() == 1)
			n.isWord = true;
		else
			addWordFromNode(word.substring(1), n);
	}
	
	private boolean checkWordFromNode(String word, Node node) {
		Node n = findChar(word.charAt(0), node.children);
		
		if (n == null)
			return false;
			
		if (word.length() == 1)
			return true;
		else
			return checkWordFromNode(word.substring(1), n);
	}
	
	public void addWord(String word) {
		++words;
		letters += word.length();
		
		addWordFromNode(word, root);
	}
	
	public boolean checkWord(String word) {
		return checkWordFromNode(word, root);
	}
	
	public String getMemory() {
		int bytes = nodes*(4+4+4+4) + nodes;
		
		return bytes/1024 + " KB";
	}
	
	public TreeDictionaryNodeIterator nodesIterator() {
		return new TreeDictionaryNodeIterator() {

			Node node = root;
			
			@Override
			public char get() {
				return node.value;
			}

			@Override
			public boolean isWord() {
				return node.isWord;
			}

			@Override
			public boolean next(char c) {
				Node t = findChar(c, node.children);
				if (t == null)
					return false;
				
				node = t;
				return true;
			}

			@Override
			public void prev() {
				node = node.parent; 				
			}
			
		};
	}

}
